#pragma once
#include"index.hpp"
#include"tool.hpp"
#include"Log.hpp"
#include<algorithm>
#include <unordered_map>
#include <jsoncpp/json/json.h>
#include"Log.hpp"

namespace ns_search{
    //  进行对重复的单词进行合并统计，weight相加，单词用vector在一起
    using namespace Log_Module;
    struct InvertedElem_p
    {
        uint64_t doc_id;
        int weight;
        std::vector<std::string> words; 
        InvertedElem_p():doc_id(0),weight(0){}
    };

    class Search{
        private:
            //根据索引进行查找
            ns_index::Index* _index;
        public:
            Search(){}
            ~Search(){}
        public:
            void InitSearch(const std::string&input)
            {
                _index=ns_index::Index::GetInstance();
                LOG(Log_Level::INFO)<<"获取单例成功";
                _index->BuildIndex(input);
                LOG(Log_Level::INFO)<<"建立正排，倒排索引成功";
            }
            //key是搜索关键字
            //json_string是返回用户浏览器的结果
            void Search_string(const std::string&key,std::string*Json_string)
            {
                //进行分词操作
                std::vector<std::string> words;
                tool_a::Jieba_tool::Separate_String(key,&words);
                //进行index查找
                std::vector<InvertedElem_p> _List_all;
                std::unordered_map<uint64_t,InvertedElem_p> token;

                for(std::string& e:words)
                {
                    boost::to_lower(e);
                    ns_index::InveredList* inverted_list=_index->GetInvertedList(e);
                    if(inverted_list==nullptr)
                    {
                        std::cout<<"查找文件为空"<<std::endl;
                        continue;
                    }
                    //进行对词的判断，，如果id相同,则合并在一起
                    for(const auto& x:*inverted_list)
                    {
                        auto& t=token[x.doc_id];
                        t.doc_id=x.doc_id;
                        t.weight+=x.weight;
                        t.words.push_back(x.word);
                    }
                    for(const auto &item : token)
                        _List_all.push_back(std::move(item.second));
                   
                }
                //进行根据权重进行降序排序
                std::sort(_List_all.begin(),_List_all.end(),\
                [](const InvertedElem_p&e1,InvertedElem_p&e2){
                    return e1.weight>e2.weight;
                });
                //根据差找结果构建json串
                Json::Value root;
                for(const auto&item:_List_all)
                {
                    ns_index::DocInfo* doc=_index->GetForwardIndex(item.doc_id);
                    if(doc==nullptr) continue;
                    Json::Value elem;
                    elem["title"]=doc->title;
                    elem["desc"]=GetDesc(doc->content,item.words[0]);
                    elem["url"]=doc->url;
                    elem["id"]=int(item.doc_id);
                    elem["weight"]=item.weight;
                    root.append(elem);
                }
                Json::FastWriter Writer;
                *Json_string=Writer.write(root);
            }

            std::string GetDesc(const std::string&content,const std::string&key)
            {
                int forward_stp=50;
                int behind_stp=100;
                //利用find函数
                //auto te=content.find(key);
                //利用search函数
                auto iter=std::search(content.begin(),content.end(),key.begin(),key.end(),[](int x, int y){
                    return (std::tolower(x)==std::tolower(y));
                });
                if(iter==content.end())return "Nonel";
                int pos=std::distance(content.begin(),iter);
                int start=0;
                int end=content.size()-1;

                if(pos>start+forward_stp) start=pos-forward_stp;
                if(pos<end-behind_stp)  end=pos+behind_stp;
                if(start>=end)return "None2";
                std::string desc= content.substr(start,end-start);
                desc+="...";
                return desc;
            }
    };
}